package com.hexinfo.dmpro.sparing.service.impl;

import cn.hutool.core.convert.NumberChineseFormatter;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hexinfo.dmpro.common.utils.ScanCommonConstants;
import com.hexinfo.dmpro.monitor.service.serviceparam.CmTargetParamService;
import com.hexinfo.dmpro.sparing.dao.SyncRuleConfMapper;
import com.hexinfo.dmpro.sparing.model.HotStandbyLogSource;
import com.hexinfo.dmpro.sparing.model.HotStandbyLogTable;
import com.hexinfo.dmpro.sparing.model.SyncRuleConf;
import com.hexinfo.dmpro.sparing.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * 有源分区字段热备方法
 */
@Service
@Slf4j
public class WarnServiceImpl implements WarnService {
    @Autowired
    private CmTargetParamService cmTargetParamService;
    @Autowired
    private SyncRuleConfMapper syncRuleConfMapper;
    @Autowired
    private HotStandbyLogSourceService hotStandbyLogSourceService;
    @Autowired
    private HotStandbyLogTableService hotStandbyLogTableService;

    @Value("${warn.warnAllSourceState}")
    private String warnAllSourceState;
    @Value("${warn.warnFailSourceState}")
    private String warnFailSourceState;
    @Value("${warn.sendWarn}")
    private String sendWarn;

    /**
     * 源执行失败告警
     * @return
     */
    @Override
    public boolean warnSourceFail(String id) {
        HotStandbyLogSource hotStandbyLogSource = hotStandbyLogSourceService.getById(id);
        List<HotStandbyLogTable> hotStandbyLogTables = hotStandbyLogTableService.queryLikeList(id, ScanCommonConstants.ClusterName.SB.value);
        Map<String, List<HotStandbyLogTable>> failTypeMap = hotStandbyLogTables.stream().collect(Collectors.groupingBy(HotStandbyLogTable::getTaskState));
        String warnAlert = StrUtil.format("{}失败详情：\n【{}】- {}（{}--{}）\n",
                hotStandbyLogSource.getSourceName(),
                hotStandbyLogSource.getTaskState(),
                hotStandbyLogSource.getTaskDate(),
                hotStandbyLogSource.getSyncRangeStartTime(),
                hotStandbyLogSource.getSyncRangeEndTime());
        for (String key : failTypeMap.keySet()) {
            List<HotStandbyLogTable> hotStandbyLogTables1 = failTypeMap.get(key);
            for (HotStandbyLogTable hotStandbyLogTable : hotStandbyLogTables1) {
                warnAlert += StrUtil.format("\t{} - {}\n",
                        hotStandbyLogTable.getTaskState(),
                        hotStandbyLogTable.getDbTbName());
            }
        }
        //发送告警,所有源执行情况
        sendWarn(warnAlert.trim(),warnFailSourceState);
//        cmTargetParamService.warnWxDingDingAndLog1("cmFlag","所有集群","clusterFlag","所有子集群","所有服务",warnAlert.trim(),warnFailSourceState);
        return true;
    }

    public void sendWarn(String warnAlert,String publishTheme) {
        log.warn("【远程告警api】:" + sendWarn);
        // 构建请求参数
        JSONObject params = new JSONObject();
        params.put("warnAlert", warnAlert);
        params.put("publishTheme", publishTheme);
        String result = HttpUtil.createPost(sendWarn)
                .body(params.toString())
                .timeout(20000) // 设置超时时间
                .execute()
                .body();
        // 打印响应结果
        log.warn("【远程告警响应】:" + result);
    }

    /**
     * 全部源执行情况告警
     * @return
     */
    @Override
    public boolean warnAllSourceState() {
        Map<String, List<HotStandbyLogSource>> sourceMap = gainSourceMap();
        String warnAlert = "";
        String date = DateUtil.format(DateUtil.date(), "yyyyMMdd");
        double i = 1.0;
        for (String key : sourceMap.keySet()) {
            //阿拉伯数字转换为中文数字
            String format = NumberChineseFormatter.format(i, false);
            warnAlert += "\n" + format + "、" + key + "：\n";
            List<HotStandbyLogSource> hotStandbyLogSources = sourceMap.get(key);
            int j = 1;
            for (HotStandbyLogSource hotStandbyLogSource : hotStandbyLogSources) {
                if (hotStandbyLogSource.getTaskState().equals(ScanCommonConstants.ClusterName.SB.value)) {
                    warnAlert += StrUtil.format("\t{})【{}】- {}（{}）\n",
                            j,
                            hotStandbyLogSource.getTaskState(),
                            hotStandbyLogSource.getTaskDate(),
                            hotStandbyLogSource.getSyncRangeStartTime()+"--"+hotStandbyLogSource.getSyncRangeEndTime());
                }else if (hotStandbyLogSource.getTaskState().equals(ScanCommonConstants.ClusterName.DZX.value)) {
                    warnAlert += StrUtil.format("\t{}) {} - {}\n",
                            j,
                            hotStandbyLogSource.getTaskState(),
                            date);
                }else {
                    warnAlert += StrUtil.format("\t{}) {} - {}（{}）\n",
                            j,
                            hotStandbyLogSource.getTaskState(),
                            hotStandbyLogSource.getTaskDate(),
                            hotStandbyLogSource.getSyncRangeStartTime()+"--"+hotStandbyLogSource.getSyncRangeEndTime());
                }
                j++;
            }
            i++;
        }
        //发送告警,所有源执行情况
        cmTargetParamService.warnWxDingDingAndLog1("cmFlag","所有集群","clusterFlag","所有子集群","所有服务","源热备执行情况：\n"+warnAlert.trim(),warnAllSourceState);
        return true;
    }

    /**
     * 获取前两天全部源执行情况
     * @return
     */
    public Map<String, List<HotStandbyLogSource>> gainSourceMap() {
        List<HotStandbyLogSource> hotStandbyLogSourceToDays = sourceHotBackupState();
        List<HotStandbyLogSource> sourceHotBackupState = hotStandbyLogSourceService.sourceHotBackupStateTwo();
        Map<String, List<HotStandbyLogSource>> sourceNameToDayMap = hotStandbyLogSourceToDays.stream().collect(Collectors.groupingBy(HotStandbyLogSource::getSourceName));
        Map<String, List<HotStandbyLogSource>> sourceNameMap = sourceHotBackupState.stream().collect(Collectors.groupingBy(HotStandbyLogSource::getSourceName));
        Map<String, List<HotStandbyLogSource>> sourceMap = new HashMap<>();
        for (String key : sourceNameToDayMap.keySet()) {
            List<HotStandbyLogSource> hotStandbyLogSources = sourceNameMap.get(key);
            if (hotStandbyLogSources != null){
                hotStandbyLogSources.addAll(sourceNameToDayMap.get(key));
                sourceMap.put(key, hotStandbyLogSources);
            }else {
                sourceMap.put(key, sourceNameToDayMap.get(key));
            }
        }
        //不存在则补充
        for (String key : sourceNameMap.keySet()) {
            if (!sourceMap.containsKey(key)) {
                sourceMap.put(key, sourceNameMap.get(key));
            }
        }
        return sourceMap;
    }

    /**
     * 获取当天全部源执行情况
     * @return
     */
    public List<HotStandbyLogSource> sourceHotBackupState() {
        //源级热备同步
        LambdaQueryWrapper<SyncRuleConf> wrapper = Wrappers.lambdaQuery();
        wrapper.select(SyncRuleConf::getSourceName)
                .groupBy(SyncRuleConf::getSourceName);
        List<SyncRuleConf> resultList = syncRuleConfMapper.selectList(wrapper);
        List<HotStandbyLogSource> sourceHotBackupState = hotStandbyLogSourceService.sourceHotBackupStateToDay();
        Map<String, List<HotStandbyLogSource>> map = sourceHotBackupState.stream().collect(Collectors.groupingBy(HotStandbyLogSource::getSourceName));
        for (SyncRuleConf syncRuleConf : resultList) {
            if (syncRuleConf == null) {
                boolean strTar = map.containsKey("无源");
                if (!strTar) {
                    HotStandbyLogSource hotStandbyLogSource = new HotStandbyLogSource();
                    hotStandbyLogSource.setSourceName("无源");
                    hotStandbyLogSource.setTaskState("待执行");
                    sourceHotBackupState.add(hotStandbyLogSource);
                }
            } else {
                boolean strTar = map.containsKey(syncRuleConf.getSourceName());
                if (!strTar) {
                    HotStandbyLogSource hotStandbyLogSource = new HotStandbyLogSource();
                    hotStandbyLogSource.setSourceName(syncRuleConf.getSourceName());
                    hotStandbyLogSource.setTaskState("待执行");
                    sourceHotBackupState.add(hotStandbyLogSource);
                }
            }
        }
        return sourceHotBackupState;
    }

}
